package com.yonyou.cloud.util;

import java.security.MessageDigest;
import java.io.Reader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileWriter;
import java.io.File;
import java.util.Scanner;
import java.util.Iterator;
import java.util.Collections;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.Enumeration;
import java.net.InetAddress;
import java.net.NetworkInterface;

public class MachineUtil
{
    public static String getMachineCode() throws Exception {
        final String macCodes = getMacIdCodes();
        final String processId = getProcesserId();
        final String machineCode = MD5(String.valueOf(macCodes) + processId, "UTF-8");
        return machineCode;
    }
    
    public static String getFistLocalIP() {
        String sIP = "";
        InetAddress ip = null;
        try {
            boolean bFindIP = false;
            final Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                if (bFindIP) {
                    break;
                }
                final NetworkInterface ni = netInterfaces.nextElement();
                final Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
                        bFindIP = true;
                        break;
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        if (ip != null) {
            sIP = ip.getHostAddress();
        }
        return sIP;
    }
    
    public static List<String> getLocalIPS() {
        InetAddress ip = null;
        final List<String> ipList = new ArrayList<String>();
        try {
            final Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                final NetworkInterface ni = netInterfaces.nextElement();
                final Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
                        ipList.add(ip.getHostAddress());
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return ipList;
    }
    
    public static String getMacId() {
        String macId = "";
        InetAddress ip = null;
        NetworkInterface ni = null;
        try {
            boolean bFindIP = false;
            final Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                if (bFindIP) {
                    break;
                }
                ni = netInterfaces.nextElement();
                final Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
                        bFindIP = true;
                        break;
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        if (ip != null) {
            try {
                macId = getMacFromBytes(ni.getHardwareAddress());
            }
            catch (SocketException e2) {
                e2.printStackTrace();
            }
        }
        return macId;
    }
    
    public static List<String> getMacIds() {
        InetAddress ip = null;
        NetworkInterface ni = null;
        final List<String> macList = new ArrayList<String>();
        try {
            final Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                ni = netInterfaces.nextElement();
                final Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
                        macList.add(getMacFromBytes(ni.getHardwareAddress()));
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return macList;
    }
    
    public static String getMacIdCodes() {
        final StringBuilder macCodes = new StringBuilder();
        final List<String> macList = new ArrayList<String>();
        InetAddress ip = null;
        NetworkInterface ni = null;
        try {
            final Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                ni = netInterfaces.nextElement();
                final Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
                        macList.add(getMacCodesFromBytes(ni.getHardwareAddress()));
                        break;
                    }
                }
            }
            Collections.sort(macList);
            for (final String mac : macList) {
                macCodes.append(mac);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return macCodes.toString();
    }
    
    private static String getMacFromBytes(final byte[] bytes) {
        final StringBuffer mac = new StringBuffer();
        boolean first = false;
        for (final byte b : bytes) {
            if (first) {
                mac.append("-");
            }
            byte currentByte = (byte)((b & 0xF0) >> 4);
            mac.append(Integer.toHexString(currentByte));
            currentByte = (byte)(b & 0xF);
            mac.append(Integer.toHexString(currentByte));
            first = true;
        }
        return mac.toString().toUpperCase();
    }
    
    private static String getMacCodesFromBytes(final byte[] bytes) {
        final StringBuffer mac = new StringBuffer();
        for (final byte b : bytes) {
            byte currentByte = (byte)((b & 0xF0) >> 4);
            mac.append(Integer.toHexString(currentByte));
            currentByte = (byte)(b & 0xF);
            mac.append(Integer.toHexString(currentByte));
        }
        return mac.toString().toUpperCase();
    }
    
    public static String getProcesserId() throws Exception {
        final Process process = Runtime.getRuntime().exec(new String[] { "wmic", "cpu", "get", "ProcessorId" });
        process.getOutputStream().close();
        final Scanner sc = new Scanner(process.getInputStream());
        sc.next();
        final String serial = sc.next();
        sc.close();
        return serial;
    }
    
    public static String getCPUSerial() {
        String result = "";
        try {
            final File file = File.createTempFile("tmp", ".vbs");
            file.deleteOnExit();
            final FileWriter fw = new FileWriter(file);
            final String vbs = "On Error Resume Next \r\n\r\nstrComputer = \".\"  \r\nSet objWMIService = GetObject(\"winmgmts:\" _ \r\n    & \"{impersonationLevel=impersonate}!\\\\\" & strComputer & \"\\root\\cimv2\") \r\nSet colItems = objWMIService.ExecQuery(\"Select * from Win32_Processor\")  \r\n For Each objItem in colItems\r\n     Wscript.Echo objItem.ProcessorId  \r\n     exit for  ' do the first cpu only! \r\nNext                    ";
            fw.write(vbs);
            fw.close();
            final Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result = String.valueOf(result) + line;
            }
            input.close();
            file.delete();
        }
        catch (Exception e) {
            e.fillInStackTrace();
        }
        if (result.trim().length() < 1 || result == null) {
            result = "\u65e0CPU_ID\u88ab\u8bfb\u53d6";
        }
        return result.trim();
    }
    
    public static String getMotherboardSN() {
        String result = "";
        try {
            final File file = File.createTempFile("realhowto", ".vbs");
            file.deleteOnExit();
            final FileWriter fw = new FileWriter(file);
            final String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\nSet colItems = objWMIService.ExecQuery _ \n   (\"Select * from Win32_BaseBoard\") \nFor Each objItem in colItems \n    Wscript.Echo objItem.SerialNumber \n    exit for  ' do the first cpu only! \nNext \n";
            fw.write(vbs);
            fw.close();
            final Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result = String.valueOf(result) + line;
            }
            input.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("MotherboardSN" + result);
        return result.trim();
    }
    
    public static String getSerialNumber(final String drive) {
        String result = "";
        try {
            final File file = File.createTempFile("realhowto", ".vbs");
            file.deleteOnExit();
            final FileWriter fw = new FileWriter(file);
            final String vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\nSet colDrives = objFSO.Drives\nSet objDrive = colDrives.item(\"" + drive + "\")\n" + "Wscript.Echo objDrive.SerialNumber";
            fw.write(vbs);
            fw.close();
            final Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result = String.valueOf(result) + line;
            }
            input.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result.trim();
    }
    
    public static final String MD5(final String pwd, final String charset) {
        final char[] md5String = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        try {
            final byte[] btInput = pwd.getBytes(charset);
            final MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            final byte[] md = mdInst.digest();
            final int j = md.length;
            final char[] str = new char[j * 2];
            int k = 0;
            for (final byte byte0 : md) {
                str[k++] = md5String[byte0 >>> 4 & 0xF];
                str[k++] = md5String[byte0 & 0xF];
            }
            return new String(str);
        }
        catch (Exception e) {
            return null;
        }
    }
}
